// 实现烟花效果的js代码
// 1. 自定义Fire构造函数
function Fire(){
  // 将获取的页面元素放到对象的属性中
  this.box = document.querySelector('.wrap');
}
// 2. 添加方法实现烟花效果的需求
// 2.1 给原型对象添加一个init方法，实现：夜空背景的样式设置并绑定点击事件
Fire.prototype.init = function(){
  // 设置夜空的样式，调用setStyle函数
  setStyle(this.box,{
    width:'100%',
    height:'100%',
    // border:'10px solid green',
    // backgroundColor:'#000',
    position:'relative'
  })
  // 给夜空背景绑定点击事件
  this.box.onmousemove = (e)=>{
    // 此处使用箭头函数，方便在函数内获取到实例对象
    // console.log(this);
    e = e || window.event;
    let left = e.offsetX;
    let top = e.offsetY;
    // let obj = {left,top};
    // 调用创建方块烟花的方法
    this.createFire({left,top});
  }
}
// 2.2 给原型添加createFire方法，实现：创建方块烟花，并设置样式
Fire.prototype.createFire = function(pObj){
  // 创建方块烟花，并设置样式
  let div = document.createElement('div');
  setStyle(div,{
    width:'10px',
    height:'10px',
    backgroundColor:getColor(),
    position:'absolute',
    bottom:0,
    left:pObj.left+'px'
  })
  // 将创建的div追加到夜空中
  this.box.appendChild(div);
  // 调用toUp方法让烟花升空
  this.toUp(div,pObj);

}
// 2.3 给原型添加toUp方法，实现：方块烟花的升空到点击的位置，然后消失
Fire.prototype.toUp = function(ele,pObj){
  // 调用运动函数实现运动升空
  move(ele,{top:pObj.top},()=>{
    // 运动到目标位置后，方块烟花消失
    ele.remove();
    // 调用创建多个小圆点烟花的方法
    this.createManyFires(pObj)
  })
}
// 2.4 给原型添加createManyFires方法，实现：创建多个小圆点烟花
Fire.prototype.createManyFires = function(pObj){
  // 生成一个随机数
  let num = getNum(3,10);
  // 循环创建小圆点烟花，并设置样式
  for (let i = 0; i < num; i++) {
    let div = document.createElement('div');
    setStyle(div,{
      width:'10px',
      height:'10px',
      backgroundColor:getColor(),
      borderRadius:'50%',
      position:'absolute',
      left:pObj.left+'px',
      top:pObj.top+'px',
    })
    // 将创建的烟花添加到夜空中
    this.box.appendChild(div);
    this.boom(div);
  }
}
// 2.5 给原型添加一个boom方法，实现：圆点烟花爆炸的效果(每个圆点烟花运动到随机的位置，然后消失)
Fire.prototype.boom = function(ele){
  // 获取随机的位置
  let x = getNum(0,this.box.clientWidth-ele.clientWidth);
  let y = getNum(0,this.box.clientHeight-ele.clientHeight);
  // 调用move函数
  move(ele,{left:x,top:y},()=>{
    // 运动结束后消失
    ele.remove();
  })
}

// 3. 实例化对象，通过对象调用方法实现效果
let fire = new Fire();
// console.log(fire);
fire.init()





/**
 *  设置元素样式的函数
 * @param {Object} ele 需要设置样式的元素
 * @param {Object} styleObj 样式对象 {left:'100px',top:'200px'}
 */
 function setStyle(ele,styleObj){
  for (let style in styleObj) {
    ele.style[style] = styleObj[style];
  }
}
/**
 * 获取随机数的函数，
 * @param {Number} n  随机数最小值
 * @param {Number} m  随机数最大值
 * @return {Number}  随机数
 */
function getNum(n,m){
  return Math.floor(Math.random()*(m-n+1)+n);
}

/**
 * 获取随机颜色的函数
 * @return {String} 返回一个随机的颜色字符串
 */
function getColor(){
  return `rgb(${getNum(0,255)},${getNum(0,255)},${getNum(0,255)})`;
}

/**
 * 封装的运动函数
 * @param {Object} ele 运动的元素
 * @param {Object} styleObj 目标样式对象
 * @param {Function} fn 运动接后执行的函数
 */
function move(ele, styleObj, fn) {
  let timerObj = {};
  for (const attr in styleObj) {
    let curStyle;
    if (attr === 'opacity') {
      curStyle = getStyle(ele, attr) * 100;
      styleObj[attr] = styleObj[attr] * 100;
    } else {
      curStyle = parseInt(getStyle(ele, attr));
    }
    timerObj[attr] = setInterval(() => {
      let goLength = (styleObj[attr] - curStyle) / 10;
      goLength = goLength > 0 ? Math.ceil(goLength) : Math.floor(goLength);
      curStyle += goLength;
      if (curStyle === styleObj[attr]) {
        clearInterval(timerObj[attr]);
        delete timerObj[attr];
        Object.keys(timerObj).length === 0?fn():'';
      } else {
        ele.style[attr] = attr==='opacity'?curStyle/100:curStyle+'px';
      }
    }, 70)
  }
}
/**
 * 封装获取元素样式的函数
 * @param {Object} ele  要获取样的元素
 * @param {String} style 获取的演示名称
 * @return {String}  返回元素对应的样式值
 */
function getStyle(ele, style) {
  try {
    return window.getComputedStyle(ele)[style];
  } catch (error) {
    return ele.currenStyle[style];
  }
}